文 / 蔡學鏞
面對越來越複雜的軟體開發需求,我們需要更高的抽象層。過去二十多年,我們將物件導向 (Object-Oriented Programming,OOP) 和元件 (Components) 的觀念注入大多數的主流 imperative 編程語言 (例如BASIC、C、Pascal),採用這些技術可以降低軟體開發的複雜度 (Complexity),增加再用性 (Reusability),於是我們著實過了好一陣子安穩的生活。
但軟體的複雜度就像細菌的抗藥性一樣,依然在持續增加。當萬古黴素開始壓制不住金黃色葡萄球菌,物件導向漸漸讓軟體開發力不從心,我們要如何是好?
越來越複雜的專業領域知識、越來越多元的異質平台、越來越普遍的網路環境和多核心電腦…這些都會提升軟體開發的複雜度,我們再度陷入困境。忽然發現,古老的函數編程 (Functional Programming,FP) 可以解決這個階段的許多問題,原來FP是現代編程問題的一帖良方。這使得最近函數編程忽然又被炒熱,成為許多語言設計者的最愛。
相較於 OOP 是往真實世界的方向進行抽象,FP 卻是往數學的方向進行抽象。FP的理論基礎是來自Lambda Calculus,而 Lambda Calculus 同時賦予 FP 簡單性和威力。當然除了 Lambda Calculus 之外,方便的 List 處理、自動記憶體管理、Meta-Programming 也都是函數式編程語言常見的特性。
提到函數編程,就不能不提 1958 年被創造出來的 LISP,因為它是函數編程的始祖。暢銷書《駭客與畫家》(Hackers and Painters) 的作者 Paul Graham 提到,LISP 是許多公司成功的秘訣,因為透過 LISP,他們可以用精簡的人力,在很短的時間內,開發出威力強大的系統。Paul Graham 本來很擔心,他這麼一鼓吹 LISP,要是別人都因此改用 LISP,自己就佔不到便宜了。不過作者最後的結論是,大多數的人不會這麼聰明,所以應該可以不必擔心。他說的沒錯,在《駭客與畫家》與《Practical Common Lisp》出版約五年後的今天,LISP 語言在 Tiobe 的語言需求排行榜卻不升反降,眼看就要被擠出前 20 名了,我直呼大師預言神準。
雖然 Paul Graham 稱讚的對象是 LISP,但等於間接稱讚到 FP。儘管一般程式開發人員對於 FP 的重視程度依然不高,但是語言設計者卻對 FP 興致高昂。既有的主流語言 (例如C#、VB) 開始在新版本中加入FP的特色;新興的語言 (例如Scala、JavaFX) 同時結合 FP 和 OOP,就連古老的 FP 語言 (例如 ML) 也有了新的面貌 (例如 F#)。
C# 為了支援 LINQ,以進行更高程度的資料查詢抽象,開始加入 FP 的特色。目前 LINQ 以經利用 FP進行 meta-programming,未來 LINQ 還會利用 FP 進行 concurrent programming,以充分利用現代多核心的運算環境。
F# 是衍生自 ML 家族的 OCaml,融合了一些C# 和 Haskell 的概念。許多時候,F# 和 OCaml 的程式是可以交互編譯的,也就是說,兩個語言的相容性很高。由於 F# 是目前 .NET 平台最重要的FP語言 (也是微軟官方提供的語言),因此未來隨著FP漸漸受到重視,F# 也會佔有一席之地。
但我認為這「一席之地」恐怕不會太大。.NET 環境下,函數式編程的語言選擇,我的建議是:如果你是基於科學、工程的目的而寫程式,那麼F#會比較適合,如果你要寫的是「世俗化的系統」(例如 Web、資料庫、RIA),那麼還是使用 C# 吧。因為既有主流語言的使用者,可以漸進式的學習函數編程。過去的經驗告訴我們,C++ 會流行、Java 會流行,某一部份的因素是因為它們是從既有的語言去做加強 (C++ 是 C 的強化版、Java 是 C/C++ 的改良版)。
但是我認為使用 C# 中語言的人,或許會因為使用 LINQ 之類的技術,而「間接」用到函數編程,但是很少有人在規劃軟體時會直接使用到函數編程的重要特色。「使用函數編程語言」不等於「進行函數編程」,你可以用函數編程語言寫出不合乎函數編程理念的程式,正如同你可以用物件導向語言寫出不合乎物件導向理念的程式。
更何況 C# 因為加入太多語言特色,變得過度複雜,開始有 C++ 化的趨勢,而「複雜」是和 FP 的「簡單」背道而馳的。因此對於初學 FP 的人,或許 F# 等「新瓶舊酒」語言會更適合用來學習FP的觀念,體會相對單純的FP經驗。
真的想學好函數編程的觀念,可能還是得從傳統的FP語言著手,會比較徹底。函數編程只是一個觀念,各個語言的作法和語法差異可能不小,例如 LISP 家族、ML 家族(F#屬於這個家族)、Erlang 這三者都是相當重要的函數編程語言,但是這三種語言的差異相當大。如果你是 .NET 使用者,就學 F#、Java 使用者就學 JavaFX 或 Scala、其他使用者就學 Common Lisp 或 Erlang。
Paradigm-Shift 總是痛苦的,但這是生存之道。從 OOP 的 Paradigm 轉移到 FP,一開始可能會有不適應的地方,但熟悉之後,你會很高興你學會了一個新的技能、新的思維,可以面對新的環境、新的挑戰。
我知道函數編程當然也不會是軟體開發一勞永逸的解決之道,未來還有更多的挑戰會出現。或許,下次的編程挑戰的救星,會是邏輯編程 (Logic Programming) 也說不定。
"Paradigm-Shift 總是痛苦的,但這是生存之道。從 OOP 的 Paradigm 轉移到 FP,一開始可能會有不適應的地方,但熟悉之後,你會很高興你學會了一個新的技能、新的思維,可以面對新的環境、新的挑戰。"
似乎其他行業的「改進」比「改變」要多
而 IT 的「改變」比「改進」要多
改了那麼多 IT 架構
那麼多程式語言工具
越改越多,越改越快
除了讓 IT 人可以混口飯吃之外,
好像也沒有太多實質上的好處